
#include "StdAfx.h"

#include "CDIADataType.h"
#include "CIDIASymb2Str.h"

#include "miscutil.h"
#include "smpio.h"

#pragma comment( lib, "comsuppw" )
#pragma comment( lib, "comsuppwd" )

void CDclFix::AppendDclFixStr(_tstring* pstr)
{
    _tstringstream ss;
    switch (enType)
    {
    case DCL_FIX_PTR:
        (*pstr)+=_T("*");
        break;

    case DCL_FIX_CNST_PTR:
        (*pstr)+=_T("*const ");
        break;

    case DCL_FIX_REF:
        (*pstr)+=_T("&");
        break;

    case DCL_FIX_ARRAY:
        ss<<_T("[")<<dwArrayDim<<_T("]");
        (*pstr)+=ss.str();
        break;

    case DCL_FIX_FUN:
        (*pstr)+=_T("()");
        break;

    default:
        ASSERT(FALSE);
        break;
    }
}


//////////////////////////////////////////////////////////////////////////
// CDIAType
//
CDIAType::CDIAType(IDiaSymbol* psymb)
            :m_pSymbDirectType(psymb)
{
    ASSERT(psymb);
    DWORD dwSysTag;
    VERIFY(SUCCEEDED(psymb->get_symTag(&dwSysTag)));
    ASSERT(    (SymTagUDT==dwSysTag) 
            || (SymTagBaseType==dwSysTag)
            || (SymTagEnum==dwSysTag )
            || (SymTagFunctionType==dwSysTag)
            || (SymTagTypedef==dwSysTag)
            || (SymTagPointerType==dwSysTag)
            || (SymTagArrayType==dwSysTag) );

    //
    // detail type info
    DWORD enSymType;
    IDiaSymbolPtr psymType=psymb;
    VERIFY(SUCCEEDED(psymType->get_symTag(&enSymType)));

    // get declare operater info
    for(int i=0; ;i++)
    {
        // a real type
        if(    (SymTagUDT==enSymType) 
            || (SymTagBaseType==enSymType)
            || (SymTagEnum==enSymType ) )
        {
            break;
        }
        // a pointer
        else if( SymTagPointerType==enSymType )
        {
            //
            // a *const
            BOOL fCnst;
            VERIFY(SUCCEEDED(psymType->get_constType(&fCnst)));
            
            if(FALSE==fCnst)
            {
                m_vDclFixExS.insert(m_vDclFixExS.begin(), CDclFixEx(psymType, DCL_FIX_PTR));
            }
            else
            {
                m_vDclFixExS.insert(m_vDclFixExS.begin(), CDclFixEx(psymType, DCL_FIX_CNST_PTR));
            }
        }
        // a array
        else if( SymTagArrayType==enSymType )
        {
            DWORD dwDim;
            VERIFY(SUCCEEDED(psymType->get_count(&dwDim)));
            m_vDclFixExS.insert(m_vDclFixExS.begin(), CDclFixEx(psymType, DCL_FIX_ARRAY, dwDim));
        }
        else if( SymTagEnum==enSymType )
        {
        }
        // typedef get the real type
        else if((SymTagTypedef==enSymType) || (SymTagFunctionType==enSymType))
        {
            m_pSymbDirectType=NULL;
            VERIFY(SUCCEEDED(psymType->get_type(&m_pSymbDirectType)));  // the type's type, for this type is a declare operator
            VERIFY(SUCCEEDED(m_pSymbDirectType->get_symTag(&enSymType)));
            psymType=NULL;
            psymType=m_pSymbDirectType;
            continue;
        }
        // other ?
        else
        {
            ASSERT(FALSE);
            break;
        }

        IDiaSymbolPtr pRealTypeSymbol;
        VERIFY(SUCCEEDED(psymType->get_type(&pRealTypeSymbol)));    // the type's type, for this type is a declare operator
        VERIFY(SUCCEEDED(pRealTypeSymbol->get_symTag(&enSymType)));

        psymType=NULL;
        psymType=pRealTypeSymbol;
    }

    // store real type
    m_pSymbTrueType=psymType;

}

BOOL CDIAType::EnumMemberData(IEnumMemberData** ppEnum, BOOL* pfPtr)
{
    if(pfPtr)
    {
        *pfPtr=FALSE;
    }

    if(0==m_vDclFixExS.size())
    {
        *ppEnum=new CUDTEnumMemberData(m_pSymbTrueType);
    }
    else if( (DCL_FIX_CNST_PTR==m_vDclFixExS.back().enType)
         || (DCL_FIX_PTR==m_vDclFixExS.back().enType)   )
    {
        if(pfPtr)
        {
            *pfPtr=TRUE;
        }
        *ppEnum=new CPtrEnumMemberData(this);	// CPtrEnumMemberData known how to retrieve point element
    }
    else if(DCL_FIX_ARRAY==m_vDclFixExS.back().enType)
    {
        *ppEnum=new CArrayEnumMemberData(this);	// CPtrEnumMemberData known how to retrieve array element
    }
    else
    {
        TRACE(_T("CUDTData::EnumChild, type:%d\r\n"), m_vDclFixExS.back().enType);
        return FALSE;
    }

    return TRUE;
}

CDclFixEx* CDIAType::GetDclFixEx()
{
	if(0==m_vDclFixExS.size())
	{
		return NULL;
	}

	return &m_vDclFixExS.back();
}

VOID CDIAType::GetTypeName(_tstring* pstrName)
{
    //is const
    BOOL fCnst;
    VERIFY(SUCCEEDED(m_pSymbTrueType->get_constType(&fCnst)));
    if(FALSE==fCnst)
    {
        *pstrName=_T("");
    }
    else
    {
        *pstrName=_T("const ");
    }
    
    // get name
    DWORD enSymType;
    VERIFY(SUCCEEDED(m_pSymbTrueType->get_symTag(&enSymType)));
    // base type
    if(SymTagBaseType==enSymType)
    {
        DWORD dwBaseType;
        VERIFY(SUCCEEDED(m_pSymbTrueType->get_baseType(&dwBaseType)));
        CIDIASymb2Str Symbol2Str(m_pSymbTrueType);
        *pstrName+=Symbol2Str.baseType();
    }
    else
    {
        _bstr_t bstrTypeName;
        VERIFY(SUCCEEDED(m_pSymbTrueType->get_name(&bstrTypeName.GetBSTR())));
        *pstrName+=(TCHAR*)bstrTypeName;
    }

    // add the declare operater part
    _tstring cstrDclFix;
    GetDclFixStr(&cstrDclFix);
    *pstrName+=cstrDclFix;

}

VOID CDIAType::GetDclFixStr(_tstring* pcstrName)
{
    std::vector<CDclFixEx>::iterator it;
    for(it=m_vDclFixExS.begin(); it!=m_vDclFixExS.end(); it++)
    {
        switch (it->enType)
        {
        case DCL_FIX_PTR:
            (*pcstrName)+=_T("* ");
            break;

        case DCL_FIX_CNST_PTR:
            (*pcstrName)+=_T(" *const ");
            break;

        case DCL_FIX_REF:
            (*pcstrName)+=_T("&");
            break;

        case DCL_FIX_ARRAY:
		{
			_tstringstream ss;
			ss<<_T("[")<<it->dwArrayDim<<_T("]");
			(*pcstrName)+=ss.str();
//			  pcstrName->AppendFormat(_T("[%d]"), rit->dwArrayDim);
			break;
        }

        case DCL_FIX_FUN:
            (*pcstrName)+=_T("()");
            break;

        default:
            ASSERT(FALSE);
            break;
        }
    }
}

DWORD CDIAType::GetLen()
{
    // type len
    ULONGLONG ull;
    VERIFY(SUCCEEDED(m_pSymbDirectType->get_length(&ull)));
    return (DWORD)(ull);
}

BOOL CDIAType::IsConst()
{
    BOOL fCnst;
    VERIFY(SUCCEEDED(m_pSymbDirectType->get_constType(&fCnst)));
    return fCnst;
}

BOOL CDIAType::IsPtr()
{
    DWORD enSymType;
    VERIFY(SUCCEEDED(m_pSymbDirectType->get_symTag(&enSymType)));
    if( SymTagPointerType==enSymType )
    {
        return TRUE;
    }
    return FALSE;
}

BOOL CDIAType::IsArray()
{
    DWORD enSymType;
    VERIFY(SUCCEEDED(m_pSymbDirectType->get_symTag(&enSymType)));
    if( SymTagArrayType==enSymType )
    {
        return TRUE;
    }
    return FALSE;
}

BOOL CDIAType::IsEnum()
{
    DWORD enSymType;
    VERIFY(SUCCEEDED(m_pSymbDirectType->get_symTag(&enSymType)));
    if( SymTagEnum==enSymType )
    {
        return TRUE;
    }
    return FALSE;
}

DWORD CDIAType::GetBaseType()
{
    DWORD dwBaseType;
    VERIFY(SUCCEEDED(m_pSymbDirectType->get_baseType(&dwBaseType)));
    return dwBaseType;
}

DWORD CDIAType::GetUdtKind()
{
    DWORD dwUdtType;
    if(SUCCEEDED(m_pSymbDirectType->get_udtKind(&dwUdtType)))
    {
        return dwUdtType;
    }

    return (DWORD)(-1);
}

BOOL CDIAType::PopFixEx()
{
    if( (DCL_FIX_PTR==m_vDclFixExS.back().enType)
        || (DCL_FIX_CNST_PTR==m_vDclFixExS.back().enType)
        || (DCL_FIX_ARRAY==m_vDclFixExS.back().enType) )
    {
        m_vDclFixExS.pop_back();
        return TRUE;
    }

    return FALSE;
}


BOOL CDIAType::GetTypeId(DWORD* pdwId)
{
    VERIFY(SUCCEEDED(m_pSymbDirectType->get_symIndexId(pdwId)));
    return TRUE;
}

DWORD CDIAComposeType::GetLen()
{
    DWORD dwOrgLen=CDIAType::GetLen();
    DWORD dwMul=1;

    for(DWORD i=0; i<m_dwAddFixNumb; i++)
    {
        if( (DCL_FIX_PTR==m_vDclFixExS[m_vDclFixExS.size()-1-i].enType)
    		|| (DCL_FIX_CNST_PTR==m_vDclFixExS[m_vDclFixExS.size()-1-i].enType) )
        {
            dwOrgLen=sizeof(int*);
            break;
        }
		// not pointer, so must array
		ASSERT(DCL_FIX_ARRAY==m_vDclFixExS[m_vDclFixExS.size()-1-i].enType);
        dwMul*=m_vDclFixExS[m_vDclFixExS.size()-1-i].dwArrayDim;
    }

    return dwMul*dwOrgLen;
}

BOOL CDIAComposeType::IsConst()
{
    if( (!m_fConst)
        && ( m_dwAddFixNumb==0 ) )
    {
        return CDIAType::IsConst();
    }

    return m_fConst;
}

BOOL CDIAComposeType::IsPtr()
{
    if( m_dwAddFixNumb==0 )
    {
        return CDIAType::IsPtr();
    }

        if( (DCL_FIX_PTR==m_vDclFixExS[m_vDclFixExS.size()-1].enType)
            || (DCL_FIX_CNST_PTR==m_vDclFixExS[m_vDclFixExS.size()-1].enType) )
        {
            return TRUE;
        }
        
    return FALSE;
}

BOOL CDIAComposeType::IsArray()
{
    if( m_dwAddFixNumb==0 )
    {
        return CDIAType::IsArray();
    }

        if(DCL_FIX_ARRAY==m_vDclFixExS[m_vDclFixExS.size()-1].enType)
        {
            return TRUE;
        }
        
    return FALSE;
}

BOOL CDIAComposeType::PushPtr(BOOL fConst)
{
    enDclFixTp op;
    if(fConst)
    {
        op=DCL_FIX_CNST_PTR;
    }
    else
    {
       op=DCL_FIX_PTR;
    }
    m_vDclFixExS.push_back(CDclFixEx(NULL, op));
    m_dwAddFixNumb++;
    return TRUE;
}

BOOL CDIAComposeType::PushDim(DWORD dwDim)
{
    m_vDclFixExS.push_back(CDclFixEx(NULL, DCL_FIX_ARRAY, dwDim));
    m_dwAddFixNumb++;
    return TRUE;
}

BOOL CDIAComposeType::PushFix(CDclFix* pFix)
{
	m_vDclFixExS.push_back(CDclFixEx(NULL, pFix->enType, pFix->dwArrayDim));
    m_dwAddFixNumb++;
    return TRUE;
}

BOOL CDIAComposeType::PopFixEx()
{
	if(FALSE==CDIAType::PopFixEx())
	{
		return FALSE;
	}
	
	if(m_dwAddFixNumb>0)
	{
		m_dwAddFixNumb--;
	}

	return TRUE;
}

VOID IDIAData::GetDataDescriptor(_tstring* pcstrDes)
{
    if(IsStatic())
    {
        *pcstrDes=_T("static ");
    }
	else
	{
		pcstrDes->clear();
	}
}

//////////////////////////////////////////////////////////////////////////
// CDIAData
//
CDIAData::CDIAData(IDiaSymbol* psymbolData)
            :m_pSymbData(psymbolData)
            ,m_fIsBitField(FALSE)
            ,m_dwArryId(INVALID_DWORD)
{
    ASSERT(NULL!=psymbolData);
    
    // must be a "data"
    DWORD SymTag;
    ASSERT(SUCCEEDED(m_pSymbData->get_symTag(&SymTag)));
    ASSERT(    (SymTagData==SymTag)
            || (SymTagBaseClass==SymTag) );
            
    // get bit info
    DWORD dwLocTp;
    VERIFY(SUCCEEDED(m_pSymbData->get_locationType(&dwLocTp)));
    if(LocIsBitField==dwLocTp)
    {
        m_fIsBitField=TRUE;
        VERIFY(SUCCEEDED(m_pSymbData->get_bitPosition(&m_dwBitPos)));
        ULONGLONG ull;
        VERIFY(SUCCEEDED(m_pSymbData->get_length(&ull)));
        m_dwBitLen=(DWORD)(ull);
    }

    IDiaSymbol* disSymb; 
    VERIFY(SUCCEEDED(m_pSymbData->get_type(&disSymb)));
    m_autopType.reset(new CDIAType(disSymb));

}

 VOID CDIAData::GetDataName(_tstring* pcstrName)
{
    *pcstrName=_T("");
    _bstr_t bstrTypeName;
    VERIFY(SUCCEEDED(m_pSymbData->get_name(&bstrTypeName.GetBSTR())));
    *pcstrName=(TCHAR*)bstrTypeName;

    // is a array member
    if(DWORD(-1)!=m_dwArryId)
    {
        _tstringstream ss;
        ss<<_T("[")<<m_dwArryId<<_T("]");
        *pcstrName+=ss.str();
    }
}

BOOL CDIAData::GetOffset(long* plOffset)
{
    // is a array member
    if(DWORD(-1)!=m_dwArryId)
    {
        *plOffset=m_dwArryId*m_autopType->GetLen();
        return TRUE;
    }

    if(m_pSymbData==NULL)
    {
        return FALSE;
    }

    // this rel
    DWORD dwLocTp;
    VERIFY(SUCCEEDED(m_pSymbData->get_locationType(&dwLocTp)));
    if( (LocIsThisRel==dwLocTp)
        || (LocIsBitField==dwLocTp) )
    {
        VERIFY(SUCCEEDED(m_pSymbData->get_offset(plOffset)));
        return TRUE;
    }
    
    // this baseclass or pointer
    DWORD SymTag;
    VERIFY(SUCCEEDED(m_pSymbData->get_symTag(&SymTag)));
    if( (SymTagBaseClass==SymTag)
        || (SymTagPointerType==SymTag) )
    {
        VERIFY(SUCCEEDED(m_pSymbData->get_offset(plOffset)));
        return TRUE;
    }
    
    return FALSE;
}

BOOL CDIAData::IsStatic()
{
    if(m_pSymbData!=NULL)
    {
        DWORD dwLocTp;
        VERIFY(SUCCEEDED(m_pSymbData->get_locationType(&dwLocTp)));
        if(LocIsStatic==dwLocTp)
        {
            return TRUE;
        }
    }
    return FALSE;
}

BOOL CDIAData::GetBitInfo(DWORD* pdwPos, DWORD* pdwLen)
{
    if(FALSE!=m_fIsBitField)
    {
        *pdwPos=m_dwBitPos;
        *pdwLen=m_dwBitLen;
        return TRUE;
    }
    return FALSE;
}

BOOL CDIAData::GetDataId(DWORD* pdwId)
{
    VERIFY(SUCCEEDED(m_pSymbData->get_symIndexId(pdwId)));
    return TRUE;
}



BOOL CPseudoDIAData::GetOffset(long* plOffset)
{
	*plOffset=m_dwOffset;

    // is a array member
    if(DWORD(-1)!=m_dwArryId)
    {
        *plOffset+=m_dwArryId*m_autopDiaType->GetLen();
        return TRUE;
    }

	return TRUE;
};

VOID CPseudoDIAData::GetDataName(_tstring* pstrName)
{
	*pstrName=m_strName;

	// is a array member
	if(DWORD(-1)!=m_dwArryId)
	{
		_tstringstream ss;
		ss<<_T("[")<<m_dwArryId<<_T("]");
		*pstrName+=ss.str();
	}
};


//////////////////////////////////////////////////////////////////////////
// CUDTDataPtrEnum
//
BOOL CUDTEnumMemberData::Next(IDIAData** ppDiaData)
{
    DWORD celt;
    IDiaSymbolPtr pSymb;

    if( (m_pEnumBaseClass!=NULL)
        && SUCCEEDED( m_pEnumBaseClass->Next( 1, &pSymb, &celt ) )
        && (celt == 1) )
    {
        *ppDiaData=new CDIAData(pSymb);
        return TRUE;
    }
    else if( (m_pEnumBaseClass!=NULL)
            && SUCCEEDED( m_pEnumData->Next( 1, &pSymb, &celt ) )
            && (celt == 1)  )
    {

        *ppDiaData=new CDIAData(pSymb);
        return TRUE;
    }

    *ppDiaData=NULL;
    return FALSE;
}

//////////////////////////////////////////////////////////////////////////
// CPtrEnumMemberData
//

BOOL CPtrEnumMemberData::Next(IDIAData** ppDiaData)
{
    if(1<=m_dwChldCnt)
    {
        return FALSE;
    }

	CDclFixEx* pFixEx=m_pDiaType->GetDclFixEx();
    ASSERT(  (DCL_FIX_PTR==pFixEx->enType) 
            || (DCL_FIX_CNST_PTR==pFixEx->enType));

    if(pFixEx->pSymb)
    {
		IDiaSymbolPtr psymbType; 
		VERIFY(SUCCEEDED(pFixEx->pSymb->get_type(&psymbType))); 	// for array and pointer can get type's type:)
		*ppDiaData=new CPseudoDIAData(psymbType);
    }
    // should be a CDIAComposeType
    else
    {
        CDIAComposeType* pComposeType;
		m_pDiaType->Clone((IDIAType **)&pComposeType);
        pComposeType->PopFixEx();
        *ppDiaData= new CPseudoDIAData(pComposeType);
    }

    m_dwChldCnt++;
    return TRUE;
}

//////////////////////////////////////////////////////////////////////////
// CArrayEnumMemberData
//

BOOL CArrayEnumMemberData::Next(IDIAData** ppDiaData)
{
	CDclFixEx* pFixEx=m_pDiaType->GetDclFixEx();
    ASSERT(DCL_FIX_ARRAY==pFixEx->enType);

	if(m_dwCurId<pFixEx->dwArrayDim)
    {
        if(pFixEx->pSymb)
        {
			IDiaSymbolPtr psymbType; 
			VERIFY(SUCCEEDED(pFixEx->pSymb->get_type(&psymbType)));		// for array and pointer can get type's type:)
            CPseudoDIAData* pDiaData=new CPseudoDIAData(psymbType);
            // set index
			pDiaData->SetDataArrayId(m_dwCurId);
            *ppDiaData=pDiaData;
        }
        // should be a CDIAComposeType
        else
        {
			CDIAComposeType* pComposeType;
			m_pDiaType->Clone((IDIAType **)&pComposeType);
            pComposeType->PopFixEx();

			CPseudoDIAData* pDiaData=new CPseudoDIAData(pComposeType);
			pDiaData->SetDataArrayId(m_dwCurId);
			*ppDiaData=pDiaData;
        }

        m_dwCurId++;
        return TRUE;

    }
    return FALSE;
}


CDIADataType::CDIADataType(IDiaSymbol* pSymbData, IDiaSymbol* pSymbType)
	:m_pEnum(NULL)
{
	ASSERT( (NULL!=pSymbData) || (NULL!=pSymbType));
	
	if(pSymbData)
	{
		m_pData.reset(new CDIAData(pSymbData));
		IDIAType* pType;
		m_pData->GetType()->Clone(&pType);
		m_pType.reset(pType);
	}
	else
	{
		m_pData.reset(new IDIAData);
		m_pType.reset(new CDIAType(pSymbType));
	}
}

CDIADataType::CDIADataType(IDIAData* pIDiaData)
	:m_pEnum(NULL)
{
	IDIAData* pData;
	pIDiaData->Clone(&pData);
	m_pData.reset(pData);

	IDIAType* pType;
	m_pData->GetType()->Clone(&pType);
	m_pType.reset(pType);
}

CDIADataType::CDIADataType(IDIAType* pIDiaType)
	:m_pEnum(NULL)
{
	m_pData.reset(new IDIAData);

	IDIAType* pType;
	pIDiaType->Clone(&pType);
	m_pType.reset(pType);
}


BOOL CDIADataType::NextChild(CDIADataType** ppDiaDataType,  BOOL* pfPtr)
{
	if(m_pEnum==NULL)
	{
		IEnumMemberData* pEnum;
		m_pType->EnumMemberData(&pEnum, pfPtr);
		m_pEnum=pEnum;
	}

	IDIAData* pData;
	if(m_pEnum->Next(&pData))
	{
		*ppDiaDataType=new CDIADataType(pData);
		delete pData;
		return TRUE;
	}
	else
	{
		return FALSE;
	}

}

VOID CDIADataType::Reset()
{
	if(m_pEnum!=NULL)
	{
		m_pEnum->Reset();
	}
}


/*
BOOL FindData(IDiaSymbol* pDiaSymbol, TCHAR* pszData, IDIAData** ppIDIAData)
{
	IDiaEnumSymbolsPtr pEnum;
	IDiaSymbol* psymbolChild;

	WCHAR* pwszData;
#ifdef UNICODE
	pwszData=pszData;
#else
	WCHAR wszData[1024];
	pwszData=wszData;
	size_t tmp;
	mbstowcs_s(&tmp, wszData, ARRAYOF(wszData), pszData, strlen(pszData));
#endif

	if( (SUCCEEDED(pDiaSymbol->findChildren(SymTagData, pwszData, 0, &pEnum)))
		&& (pEnum!=NULL) ) // sometimes even findchidren success, but the pEnum is null!!!
	{
		DWORD celt;
		// should be only one, so used the first
		if(SUCCEEDED( pEnum->Next( 1, &psymbolChild, &celt ) ) && celt == 1) 
		{
			*ppIDIAData=new CDIAData(psymbolChild);
			return TRUE;
		}
	}

	return FALSE;
}


BOOL FindType(IDiaSymbol* pDiaSymbol, TCHAR* pszType, IDIAType** ppIDIAType)
{
    IDiaEnumSymbolsPtr pEnum;
    IDiaSymbol* psymbolChild;

    WCHAR* pwszType;
#ifdef UNICODE
    pwszType=pszType;
#else
    WCHAR wszType[1024];
    pwszType=wszType;
    size_t tmp;
    mbstowcs_s(&tmp, wszType, ARRAYOF(wszType), pszType, strlen(pszType));
#endif


    DWORD  dwChldCnt;
    enum SymTagEnum enTpS[]={SymTagUDT, SymTagTypedef, SymTagEnum, SymTagBaseType};
    for(DWORD i=0; i<sizeof(enTpS)/sizeof(enTpS[0]); i++)
    {
        if( (SUCCEEDED(pDiaSymbol->findChildren(enTpS[i], pwszType, 0, &pEnum)))
        	&& (pEnum!=NULL) ) // sometimes even findchidren success, but the pEnum is null!!!
        {
            DWORD celt;
            // should be only one, so used the first
            if(SUCCEEDED( pEnum->Next( 1, &psymbolChild, &celt ) ) && celt == 1) 
            {
                *ppIDIAType=new CDIAType(psymbolChild);
                return TRUE;
            }
        }
    }
    
    // not find maybe a decleare
    CDeclare dcl(pszType);
    if(!dcl.Parse())
    {
        return FALSE;
    }

    tstring strType;
    if(dcl.IsDiaBaseType())
    {
        BaseTypeInfo byi;
        dcl.GetBasicTypeDiaInfo(&byi);
    }
    else
    {
        dcl.GetType(&strType);

        enum SymTagEnum enTpS[]={SymTagUDT, SymTagTypedef, SymTagEnum, SymTagBaseType};
        for(DWORD i=0; i<sizeof(enTpS)/sizeof(enTpS[0]); i++)
        {
            if( (SUCCEEDED(pDiaSymbol->findChildren(enTpS[i], strType, 0, &pEnum)))
            	&& (pEnum!=NULL) ) // sometimes even findchidren success, but the pEnum is null!!!
            {
                DWORD celt;
                // should be only one, so used the first
                if(SUCCEEDED( pEnum->Next( 1, &psymbolChild, &celt ) ) && celt == 1) 
                {
                    *ppIDIAType=new CDIAType(psymbolChild);
                    return TRUE;
                }
            }
        }
    }

}

*/


